import OpenAI from 'openai';
import { DeepSeekConfig, DeepSeekResponse, CommandResult } from '../types';
import { logger } from '../utils/logger';
import { validateTaskDescription, validateDeepSeekConfig } from '../utils/validators';

export class DeepSeekClient {
  private client: OpenAI;
  private config: DeepSeekConfig;

  constructor(config: DeepSeekConfig) {
    validateDeepSeekConfig(config);
    this.config = config;
    this.client = new OpenAI({
      apiKey: config.apiKey,
      baseURL: config.baseURL || 'https://api.deepseek.com/v1',
    });
  }

  async analyzeTask(taskDescription: string, systemInfo?: string): Promise<DeepSeekResponse> {
    try {
      validateTaskDescription(taskDescription);
      logger.info(`分析任务: ${taskDescription}`);

      const systemPrompt = `你是一个Linux系统运维专家助手。用户会向你描述需要在远程Linux服务器上执行的任务，你需要：

1. 理解任务需求
2. 提供具体的Linux命令序列
3. 解释每个命令的作用
4. 考虑安全性和最佳实践

${systemInfo ? `当前系统信息：\n${systemInfo}` : ''}

请以JSON格式回复，包含以下字段：
- reasoning: 任务分析和思路
- commands: 需要执行的命令数组
- description: 整体描述

注意：
- 只提供安全的、必要的命令
- 避免危险操作如rm -rf /等
- 考虑命令的执行顺序和依赖关系
- 命令应该具体可执行，避免占位符

示例回复格式：
{
  "reasoning": "需要安装nginx Web服务器并启动服务",
  "commands": [
    "sudo apt update",
    "sudo apt install -y nginx",
    "sudo systemctl start nginx",
    "sudo systemctl enable nginx"
  ],
  "description": "安装并启动nginx服务"
}`;

      const response = await this.client.chat.completions.create({
        model: this.config.model || 'deepseek-chat',
        max_tokens: this.config.maxTokens || 4096,
        messages: [
          {
            role: 'system',
            content: systemPrompt
          },
          {
            role: 'user',
            content: taskDescription
          }
        ],
        temperature: 0.1,
      });

      const content = response.choices[0]?.message?.content;
      if (!content) {
        throw new Error('DeepSeek响应为空');
      }

      let parsedResponse;

      try {
        // 尝试提取JSON
        const jsonMatch = content.match(/\{[\s\S]*\}/);
        if (jsonMatch) {
          parsedResponse = JSON.parse(jsonMatch[0]);
        } else {
          // 如果没有JSON，尝试解析文本
          parsedResponse = {
            reasoning: content,
            commands: this.extractCommandsFromText(content),
            description: taskDescription
          };
        }
      } catch (parseError) {
        logger.warn('无法解析JSON响应，使用文本解析');
        parsedResponse = {
          reasoning: content,
          commands: this.extractCommandsFromText(content),
          description: taskDescription
        };
      }

      const deepseekResponse: DeepSeekResponse = {
        id: response.id,
        content: content,
        commands: parsedResponse.commands || [],
        reasoning: parsedResponse.reasoning || content
      };

      logger.info(`DeepSeek分析完成，生成了 ${deepseekResponse.commands?.length || 0} 个命令`);
      return deepseekResponse;
    } catch (error) {
      logger.error(`DeepSeek API调用失败: ${error}`);
      throw error;
    }
  }

  async analyzeResults(originalTask: string, commandResults: CommandResult[]): Promise<DeepSeekResponse> {
    try {
      logger.info('分析命令执行结果');

      const resultsText = commandResults.map((result, index) =>
        `命令 ${index + 1}: ${result.command}
退出码: ${result.exitCode}
标准输出: ${result.stdout}
错误输出: ${result.stderr}
执行时间: ${result.timestamp.toISOString()}
---`
      ).join('\n');

      const systemPrompt = `你是一个Linux系统运维专家。用户刚才执行了一系列命令来完成任务，请分析执行结果：

1. 判断任务是否成功完成
2. 如果有错误，提供解决方案
3. 如果需要额外步骤，提供相关命令
4. 总结执行情况

请以JSON格式回复，包含以下字段：
- success: 是否成功（boolean）
- summary: 执行结果总结
- issues: 发现的问题（数组）
- recommendations: 建议的后续操作
- additional_commands: 如需要，提供额外命令（数组）

示例回复格式：
{
  "success": true,
  "summary": "所有命令执行成功，nginx已安装并启动",
  "issues": [],
  "recommendations": ["建议配置防火墙规则"],
  "additional_commands": ["sudo ufw allow 80", "sudo ufw allow 443"]
}`;

      const userMessage = `原始任务: ${originalTask}

执行结果:
${resultsText}`;

      const response = await this.client.chat.completions.create({
        model: this.config.model || 'deepseek-chat',
        max_tokens: this.config.maxTokens || 4096,
        messages: [
          {
            role: 'system',
            content: systemPrompt
          },
          {
            role: 'user',
            content: userMessage
          }
        ],
        temperature: 0.1,
      });

      const content = response.choices[0]?.message?.content;
      if (!content) {
        throw new Error('DeepSeek响应为空');
      }

      let parsedResponse;

      try {
        const jsonMatch = content.match(/\{[\s\S]*\}/);
        if (jsonMatch) {
          parsedResponse = JSON.parse(jsonMatch[0]);
        } else {
          parsedResponse = {
            summary: content,
            recommendations: []
          };
        }
      } catch (parseError) {
        logger.warn('无法解析结果分析JSON响应');
        parsedResponse = {
          summary: content,
          recommendations: []
        };
      }

      const deepseekResponse: DeepSeekResponse = {
        id: response.id,
        content: content,
        commands: parsedResponse.additional_commands || [],
        reasoning: parsedResponse.summary || content
      };

      logger.info('命令执行结果分析完成');
      return deepseekResponse;
    } catch (error) {
      logger.error(`结果分析失败: ${error}`);
      throw error;
    }
  }

  private extractCommandsFromText(text: string): string[] {
    const commands: string[] = [];

    // 提取代码块中的命令
    const codeBlockRegex = /```(?:bash|sh|shell)?\s*\n([\s\S]*?)\n```/g;
    let match;

    while ((match = codeBlockRegex.exec(text)) !== null) {
      const codeBlock = match[1];
      const lines = codeBlock.split('\n')
        .map(line => line.trim())
        .filter(line => line && !line.startsWith('#'));
      commands.push(...lines);
    }

    // 提取行内命令
    const inlineCommandRegex = /`([^`]+)`/g;
    while ((match = inlineCommandRegex.exec(text)) !== null) {
      const command = match[1].trim();
      if (this.isLinuxCommand(command)) {
        commands.push(command);
      }
    }

    // 去重并返回
    return [...new Set(commands)];
  }

  private isLinuxCommand(text: string): boolean {
    const linuxCommands = [
      'ls', 'cd', 'pwd', 'mkdir', 'rmdir', 'rm', 'cp', 'mv', 'find', 'grep',
      'cat', 'less', 'head', 'tail', 'chmod', 'chown', 'ps', 'kill', 'top',
      'df', 'du', 'free', 'uname', 'whoami', 'id', 'groups', 'sudo', 'su',
      'systemctl', 'service', 'netstat', 'ss', 'iptables', 'ping', 'curl',
      'wget', 'tar', 'gzip', 'gunzip', 'zip', 'unzip', 'vi', 'vim', 'nano',
      'yum', 'apt', 'apt-get', 'dpkg', 'rpm', 'git', 'docker', 'npm', 'node',
      'python', 'pip', 'java', 'make', 'gcc', 'mysql', 'redis', 'nginx'
    ];

    const firstWord = text.split(/\s+/)[0];
    return linuxCommands.includes(firstWord) || text.includes('./') || text.includes('/');
  }

  async getSystemInfo(sessionId: string, sshManager: any): Promise<string> {
    try {
      const infoCommands = [
        'uname -a',
        'cat /etc/os-release 2>/dev/null || cat /etc/redhat-release 2>/dev/null || echo "Unknown OS"',
        'df -h',
        'free -h',
        'whoami',
        'pwd'
      ];

      const results = await sshManager.executeMultipleCommands(sessionId, infoCommands);

      return results.map((result: any) =>
        `${result.command}:\n${result.stdout}\n`
      ).join('\n');
    } catch (error) {
      logger.warn(`获取系统信息失败: ${error}`);
      return '';
    }
  }
}